438. 找到字符串中所有字母异位词

给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。

字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100。

说明:

  • 字母异位词指字母相同,但排列不同的字符串。
  • 不考虑答案输出的顺序。

示例 1:

输入:
s: "cbaebabacd" p: "abc"

输出:
[0, 6]

解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的字母异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的字母异位词。

示例 2:

输入:
s: "abab" p: "ab"

输出:
[0, 1, 2]

解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的字母异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的字母异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的字母异位词。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-all-anagrams-in-a-string


这道题的解法与下面这两道基本一致
76. 最小覆盖子串
567. 字符串的排列

需要注意的是,这道题虽然要求的是 字母异位词,结果是除了异位词,同位词也要算上

代码:

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        from collections import defaultdict
        need = defaultdict(int)
        for c in p:
            need[c] += 1
        needCnt = len(p)
        left = 0
        result = []

        for right in range(len(s)):
            if need[s[right]] > 0:
                needCnt -= 1
            need[s[right]] -= 1
            
            if needCnt == 0:
                while need[s[left]] != 0:
                    need[s[left]] += 1
                    left += 1
                
                if right - left + 1 == len(p):
                    result.append(left)
                
                need[s[left]] += 1
                needCnt += 1
                left += 1
        return result